﻿using QuantBox.XApi;
using SmartQuant;

namespace QuantBox
{
    internal class EventProcessor
    {
        private readonly QBHistoricalData _provider;

        private static void GetAttachedData(object request,
            out HistoricalDataRequest dataRequest,
            out InstrumentDefinitionRequest instrumentRequest)
        {
            dataRequest = null;
            instrumentRequest = null;
            if (request.GetType() == typeof(InstrumentDefinitionRequest)) {
                instrumentRequest = (InstrumentDefinitionRequest)request;
            }
            else {
                dataRequest = (HistoricalDataRequest)request;
            }
        }

        public EventProcessor(QBHistoricalData provider)
        {
            _provider = provider;
        }

        public void ProcessData(DataRequestInfo info, object[] data)
        {
            GetAttachedData(info.AttachedData, out var dataRequest, out var instrumentRequest);
            if (dataRequest != null) {
                DataObject[] result = null;
                switch (dataRequest.DataType) {
                    case EventType.Quote:
                    case EventType.Ask:
                    case EventType.Bid:
                    case EventType.Trade:
                    case EventType.Tick:
                        var ticks = data as DepthMarketDataField[];
                        if (dataRequest.DataType == DataObjectType.Tick || _provider.QuoteAndTrade || info.RealtimeDataRequest) {
                            result = TypeConvert.ToTradeAndQuote(ticks, dataRequest.Instrument);
                        }
                        else {
                            switch (dataRequest.DataType) {
                                case EventType.Trade:
                                    result = TypeConvert.ToTrade(ticks, dataRequest.Instrument);
                                    break;
                                case EventType.Quote:
                                    result = TypeConvert.ToQuote(ticks, dataRequest.Instrument);
                                    break;
                                default:
                                    result = TypeConvert.ToQuote(ticks, dataRequest.Instrument, dataRequest.DataType);
                                    break;
                            }
                        }
                        break;
                    case EventType.Bar:
                        var bars = data as BarDataField[];
                        result = TypeConvert.ToBar(bars, dataRequest.Instrument, dataRequest.BarSize.Value);
                        break;
                }
                if (result != null) {
                    _provider.RequestDataReady(dataRequest, result);
                }
            }
            else {
                var items = data as InstrumentData[];
                var instruments = TypeConvert.ToInstrument(items, _provider.Id);
                _provider.RequestDataReady(instrumentRequest, info, instruments);
            }
        }

        public void ProcessCancelled(DataRequestInfo info)
        {
            GetAttachedData(info.AttachedData, out var dataRequest, out var instrumentRequest);
            if (dataRequest != null) {
                _provider.RequestCancelled(dataRequest);
            }
            else {
                _provider.RequestCancelled(instrumentRequest);
            }
        }

        public void ProcessCompleted(DataRequestInfo info)
        {
            GetAttachedData(info.AttachedData, out var dataRequest, out var instrumentRequest);
            if (dataRequest != null) {
                _provider.RequestCompleted(dataRequest);
            }
            else {
                _provider.RequestCompleted(instrumentRequest);
            }
        }

        public void ProcessFailed(DataRequestInfo info, string msg)
        {
            GetAttachedData(info.AttachedData, out var dataRequest, out var instrumentRequest);
            if (dataRequest != null) {
                _provider.RequestFailed(dataRequest, msg);
            }
            else {
                _provider.RequestFailed(instrumentRequest, msg);
            }
        }
    }
}